#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mad.h>
#include <math.h>
#include "mp3-info.h"

#define INPUT_BUFFER_SIZE 16384  // 16KB缓冲区

// 处理 MAD 库错误
static enum mad_flow error_func(void *data, struct mad_stream *stream, struct mad_frame *frame) {
    fprintf(stderr, "MAD 解码错误: %s\n", mad_stream_errorstr(stream));
    return MAD_FLOW_CONTINUE;
}

/**
 * @brief 秒数转换为时分秒格式字符串
 * @param seconds 总秒数
 * @param buffer 输出缓冲区
 * @param buffer_size 缓冲区大小
 */
void format_duration(double seconds, char *buffer, size_t buffer_size) {
    int hours = (int)seconds / 3600;
    int minutes = ((int)seconds % 3600) / 60;
    int secs = (int)seconds % 60;
    int ms = (int)((seconds - floor(seconds)) * 1000);
    
    if (hours > 0) {
        snprintf(buffer, buffer_size, "%d:%02d:%02d.%03d", hours, minutes, secs, ms);
    } else {
        snprintf(buffer, buffer_size, "%02d:%02d.%03d", minutes, secs, ms);
    }
}

/**
 * @brief 使用MAD库计算MP3文件的帧数和时长
 * @param file MP3文件指针
 * @param info 用于存储MP3信息的结构体指针
 * @param verbose 是否显示详细信息
 * @return 成功返回true，失败返回false
 */
bool get_mp3_info(FILE *file, mp3_info_t *info, bool verbose) {
    struct mad_stream stream;
    struct mad_header header;
    struct mad_decoder decoder;
    unsigned char buffer[INPUT_BUFFER_SIZE];
    int result = 0;
    bool success = false;
    
    // 保存原始文件位置
    fpos_t original_pos;
    if (fgetpos(file, &original_pos) != 0) {
        if (verbose) fprintf(stderr, "无法获取文件位置\n");
        return false;
    }
    
    // 初始化信息结构体
    memset(info, 0, sizeof(mp3_info_t));
    
    // 检查文件指针
    if (file == NULL) {
        if (verbose) fprintf(stderr, "传入的文件指针为空\n");
        return false;
    }
    
    // 初始化 MAD 流和头部解析器
    mad_stream_init(&stream);
    mad_header_init(&header);
    
    // 跟踪帧计数和累积时长
    unsigned long frame_count = 0;
    double total_duration = 0.0;
    unsigned long long avg_bitrate = 0;
    
    // 跟踪缓冲区剩余数据
    int remain = 0;
    int read_size = 0;
    
    while (1) {
        // 处理剩余数据
        if (remain > 0) {
            memmove(buffer, buffer + INPUT_BUFFER_SIZE - remain, remain);
        }
        
        // 读取数据到缓冲区
        read_size = fread(buffer + remain, 1, INPUT_BUFFER_SIZE - remain, file);
        if (read_size <= 0) break;
        
        // 计算当前缓冲区中的数据总量
        size_t input_size = remain + read_size;
        
        // 将数据提供给 MAD 流
        mad_stream_buffer(&stream, buffer, input_size);
        
        // 解码每一帧的头部
        while (1) {
            if (mad_header_decode(&header, &stream) == -1) {
                if (stream.error == MAD_ERROR_BUFLEN) {
                    // 需要更多数据
                    break;
                } else if (MAD_RECOVERABLE(stream.error)) {
                    //if (verbose) fprintf(stderr, "可恢复错误: %s\n", mad_stream_errorstr(&stream));
                    continue;  // 继续处理下一帧
                } else {
                    //if (verbose) fprintf(stderr, "不可恢复错误: %s\n", mad_stream_errorstr(&stream));
                    result = -1;
                    break;
                }
            }
            
            // 统计有效帧
            frame_count++;
            
            // 计算帧时长并累加
            double frame_duration = (double)mad_timer_count(header.duration, MAD_UNITS_MILLISECONDS) / 1000.0;
            total_duration += frame_duration;
            
            // 收集其他信息 (仅首帧)
            if (frame_count == 1) {
                info->sample_rate = header.samplerate;
                info->channels = MAD_NCHANNELS(&header);
            }
            
            // 累计比特率计算
            avg_bitrate += header.bitrate;
        }
        
        if (result != 0) break;
        
        // 计算剩余数据量
        remain = stream.bufend - stream.next_frame;
        
        // 检查文件末尾
        if (feof(file) && remain == 0) break;
    }
    
    // 存储信息
    info->frame_count = frame_count;
    info->duration = total_duration;
    if (frame_count > 0) {
        info->bitrate = avg_bitrate / frame_count / 1000; // 平均比特率，kbps
        success = true;
    }
    
    // 打印信息
    if (verbose) {
        printf("MP3帧数: %lu,", info->frame_count);
        
        char duration_str[32];
        format_duration(info->duration, duration_str, sizeof(duration_str));
        printf("时长: %s (%.2f秒),", duration_str, info->duration);
        
        printf("采样率: %d Hz,", info->sample_rate);
        printf("比特率: %d kbps,", info->bitrate);
        printf("通道数: %d\n", info->channels);
    }
    
    // 清理资源
    mad_header_finish(&header);
    mad_stream_finish(&stream);
    
    // 恢复原始文件位置
    if (fsetpos(file, &original_pos) != 0) {
        if (verbose) fprintf(stderr, "无法恢复文件位置\n");
    }
    
    return success;
}
